<?php

Raise::load('core.RaiseStream');
Raise::load('core.RaiseVariable');
Raise::load('core.RaiseFile');

/**
 * RaiseFileStream class
 * Provide IO read and write streaming to a file
 *
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.IO
 * @since 1.2
 */
class RaiseFileStream extends RaiseStream {

    /**
     * Create a RaiseFileStream from a filename or
     * @param string|RaiseFile $file
     */
    public function __construct($file){

        if(RaiseVariable::isA($file, 'RaiseFile')){
            $file = $file->getPathName();
        }

        if(is_string($file)){
            $this->handle = fopen($file, 'r+');
            if(!$this->handle){
                throw new RaiseFileOperationFailedException('File \'' . $file . '\' failed to open.');
            }
        }else{
            throw new RaiseInvalidArgumentException('The argument $file \'' . $file . '\' is neither a file pathname, RaiseFile nor RaiseStream object. ');
        }
    }

    public function length() {
        $filesize = null;
        if($this->handle){
            $tmppos = ftell($this->handle);
            fseek($this->handle, 0, SEEK_END);
            $filesize = ftell($this->handle);
            fseek($this->handle, $tmppos);
        }
        return $filesize;
    }

    public function isReadable() {
        return true;
    }

    public function isSeekable() {
        return true;
    }

    public function isWriteable() {
        return true;
    }

    public function read($length) {
        $s = null;
        if($this->handle){
            $s = fread($this->handle, $length);
            $this->position(ftell($this->handle));
        }
        return $s;
    }

    public function readByte() {
        $i = null;
        if($this->handle){
            $i = ord(fread($this->handle, 1));
            $this->position(ftell($this->handle));
        }
        return $i;
    }

    public function seek($position) {
        if($this->handle){
            fseek($this->handle, $position);
            $this->position($position);
        }
    }

    public function write($str) {
        if($this->handle){
            fwrite($this->handle, $str);
            $this->position(ftell($this->handle));
        }
    }

    public function writeByte($i) {
        if($this->handle){
            fwrite($this->handle, chr($i));
            $this->position(ftell($this->handle));
        }
    }


    public function close() {
        if($this->handle){
            fclose($this->handle);
            $this->handle = null;
        }
    }
}
